package mytools

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"net"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
	"unsafe"
)

var iniNum int64

var timeNow time.Time

//Int2Byte 123
func Int2Byte(data int) (ret []byte) {
	var len uintptr = unsafe.Sizeof(data)
	ret = make([]byte, len)
	var tmp int = 0xff
	var index uint = 0
	for index = 0; index < uint(len); index++ {
		ret[index] = byte((tmp << (index * 8) & data) >> (index * 8))
	}
	return ret
}

//Byte2Int 13
func Byte2Int(data []byte) int {
	var ret int = 0
	var len int = len(data)
	var i uint = 0
	for i = 0; i < uint(len); i++ {
		ret = ret | (int(data[i]) << (i * 8))
	}
	return ret
}

//Binary2Bytes  转成byte
func Binary2Bytes(s1 interface{}) []byte {
	buf := bytes.NewBuffer(nil)
	if err := binary.Write(buf, binary.BigEndian, s1); err != nil {
		fmt.Printf("binary.Write err=%s", err)
	}
	return buf.Bytes()
}

//Binary2Struct struct 赋值
func Binary2Struct(data []byte, s2 interface{}) {
	buf2 := bytes.NewBuffer(data)
	if err := binary.Read(buf2, binary.BigEndian, s2); err != nil {
		fmt.Printf("binary.Read err=%s", err)
	}
}

//TimeStart 123
func TimeStart() {
	timeNow = time.Now()
}

//TimeEnd 123
func TimeEnd() time.Duration {
	return time.Since(timeNow)
}

func init() {
	iniNum = time.Now().Unix()
}

//Struct2String 123
func Struct2String(t interface{}) string {
	b, e := json.Marshal(t)
	if e != nil {
		return e.Error()
	}
	return string(b)
}

//Struct2bytes 123
func Struct2bytes(t interface{}) []byte {
	b, e := json.Marshal(t)
	if e != nil {
		return []byte(e.Error())
	}
	return b
}

//Bytes2Struct 13
func Bytes2Struct(b []byte, t interface{}) error {
	return json.Unmarshal(b, t)
}

//String2Int 12
func String2Int(s string) (int, error) {
	i, err := strconv.Atoi(s)
	return i, err
}

//Int2String 123
func Int2String(i int) string {
	return strconv.Itoa(i)
}

//RandBool 123
func RandBool() bool {
	rand.Seed(time.Now().Unix())
	return rand.Intn(2) == 1
}

//RandIntn 123
func RandIntn(i int) int {
	rand.Seed(time.Now().Unix())
	return rand.Intn(i)
}

//MyID 123
func MyID() string {
	return fmt.Sprintf("%x", iniNum*int64(rand.Intn(100000000))+time.Now().UnixNano())
}

//MySleep 123
func MySleep(num time.Duration) {
	time.Sleep(num * time.Second)
}

//MySleepMs 324
func MySleepMs(num time.Duration) {
	time.Sleep(num * time.Millisecond)
}

//MyTimeFormat 123
func MyTimeFormat() string {
	return time.Now().Format("2006-01-02 15:04:05")
}

//MyTime 123
func MyTime(isNano bool) int64 {
	if isNano {
		return time.Now().UnixNano()
	}
	return time.Now().Unix()

}

//MatchIsReg 13
func MatchIsReg(str string, mat string) (bool, string) {
	reg1 := regexp.MustCompile(mat)
	if reg1 == nil {
		return false, "regexp err"
	}
	return reg1.Match([]byte(str)), ""
}

//MatchReg 123
func MatchReg(str string, mat string) ([][]string, error) {
	r := make([][]string, 0)
	reg1 := regexp.MustCompile(mat)
	if reg1 == nil {
		return r, errors.New("regexp err")
	}
	return reg1.FindAllStringSubmatch(str, -1), nil

}

//MyJSON 13
func MyJSON(a string) map[string]interface{} {
	// fmt.Println(1)
	mk := make(map[string]interface{})

	err := json.Unmarshal([]byte(a), &mk)
	if err != nil {
		fmt.Println(err)
	}
	// for k, v := range mk {
	// 	// fmt.Println(k)
	// 	fmt.Printf("%s type:%T\n", k, v)
	// }
	return mk

}

//MatchJSON 134
func MatchJSON(str string, mat string) (string, string) {
	v := MyJSON(str)
	var v2 interface{}
	s := strings.Split(mat, ".")
	v2, err := v[s[0]]
	if !err {
		return "", "no " + s[0]
	}
	if len(s) > 1 {
		for _, i := range s[1:] {
			if fmt.Sprintf("%T", v2) == "[]interface {}" {
				i1, err := strconv.Atoi(i)
				if err != nil {

					return "", err.Error()
				}
				if len(v2.([]interface{})) > i1 {
					v2 = v2.([]interface{})[i1]
				} else {
					return "", "out of " + i
				}

			} else {
				_, err = v2.(map[string]interface{})
				if !err {
					return "", "no " + i
				}
				v2 = v2.(map[string]interface{})[i]

			}
		}
	}
	return StrVal(v2), ""

}

//StrVal 123
func StrVal(value interface{}) string {
	var key string
	if value == nil {
		return key
	}

	switch value.(type) {
	case float64:
		ft := value.(float64)
		key = strconv.FormatFloat(ft, 'f', -1, 64)
	case float32:
		ft := value.(float32)
		key = strconv.FormatFloat(float64(ft), 'f', -1, 64)
	case int:
		it := value.(int)
		key = strconv.Itoa(it)
	case uint:
		it := value.(uint)
		key = strconv.Itoa(int(it))
	case int8:
		it := value.(int8)
		key = strconv.Itoa(int(it))
	case uint8:
		it := value.(uint8)
		key = strconv.Itoa(int(it))
	case int16:
		it := value.(int16)
		key = strconv.Itoa(int(it))
	case uint16:
		it := value.(uint16)
		key = strconv.Itoa(int(it))
	case int32:
		it := value.(int32)
		key = strconv.Itoa(int(it))
	case uint32:
		it := value.(uint32)
		key = strconv.Itoa(int(it))
	case int64:
		it := value.(int64)
		key = strconv.FormatInt(it, 10)
	case uint64:
		it := value.(uint64)
		key = strconv.FormatUint(it, 10)
	case string:
		key = value.(string)
	case []byte:
		key = string(value.([]byte))
	default:
		newValue, _ := json.Marshal(value)
		key = string(newValue)
	}

	return key
}

//MyInput 13
func MyInput(des string) string {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print(des + ":")

	text, err := reader.ReadString('\n')
	if err != nil {
		text = ""

	} else {
		// convert CRLF to LF

		text = strings.Replace(text, "\r", "", -1)
		text = strings.Replace(text, "\n", "", -1)
	}
	return text
}

//MYClose 123
func MYClose(num int) {
	os.Exit(num)
}

//MyIP 13
func MyIP() []string {
	mm := make([]string, 0)
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		fmt.Println(err)

	}
	for _, value := range addrs {
		if ipnet, ok := value.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				mm = append(mm, ipnet.IP.String())

			}
		}
	}
	return mm
}
